/**
* Copyright (c) By zengqh.
*
* This program is just for fun or demo, in the hope that it  
* will be useful, you can redistribute it and/or modify freely.
*
* Time: 2013/03/03
* File: RenderDef.h
* Blog: http://www.cnblogs.com/zengqh/
**/

#pragma once

#include <core/Core.h>
#include <core/Flags.h>
#include <core/Noncopyable.h>

namespace HY
{
class BufferUsage
{
public:
	enum 
	{
	Static    = 0,	/** Static memory usage */

	Dynamic   = 1,	/** Dynamic memory usage */

	WriteOnly = 2,  /** Informs the system that the application writes only to the buffer.
					 Using this flag enables the driver to choose the best memory location
					 for efficient write operations and rendering. 
					 */

	Software  = 3,	/** Software memory usage (for instance temp buffers, normally no rendering possible) */

	Number    = 4,	/** Number of usage flags */
	};
};

class Lock
{
public:
	enum 
	{
		ReadOnly  = 0,	/** Read only */
		WriteOnly = 1,	/** Write only */
		ReadWrite = 2,	/** Read and write */
		Number    = 3,	/** Number of lock modes */
	};
};

class Primitive
{
public:
	enum 
	{
		PointList     = 0,	/** Point list */
		LineList      = 1,	/** Line list */
		TriangleList  = 3,	/** Triangle list */
		Number        = 4,	/** Number of primitive types */
	};
};

class CubeMapFace
{
public:
	enum
	{
		FACE_POSITIVE_X = 0,
		FACE_NEGATIVE_X,
		FACE_POSITIVE_Y,
		FACE_NEGATIVE_Y,
		FACE_POSITIVE_Z,
		FACE_NEGATIVE_Z,
		MAX_CUBEMAP_FACES
	};
};

class RenderState
{
public:
	enum
	{
		/** Modes */
		FillMode            = 0,	/** Fill mode (see Fill, default: Fill::Solid) */
		CullMode            = 1,	/** Cull mode (see Cull, RenderState::InvCullMode, default: Cull::CCW) */
		/** Z buffer */
		ZEnable             = 2,	/** Enable/disable z buffer test (false/true, default: true) */
		ZWriteEnable        = 3,	/** Enable/disable z buffer writing (false/true, default: true) */
		ZFunc               = 4,	/** Z buffer function (see Compare, default: Compare::LessEqual) */
		ZBias               = 5,	/** Z bias/polygon offset factor, < 0 = towards camera (float to PLCore::uint32 example PLCore::Tools::FloatToUInt32(-0.001f), default: 0)
										 Because RenderState::SlopeScaleDepthBias and RenderState::DepthBias below are API and
										 GPU dependent, their results are NOT the same on each system & API. Whenever possible, do NOT use
										 this 'classic' render states, use RenderState::ZBias instead. If this state is not null, the renderer
										 will automatically manipulate the internal projection matrix to perform an 'z bias' which is more
										 predictable as the 'classic' polygon offset. */
		SlopeScaleDepthBias = 6,	/** Slope scale bias/polygon offset factor, try to avoid using this -> see ZBias (float to PLCore::uint32 example PLCore::Tools::FloatToUInt32(-1.0f), default: 0) */
		DepthBias           = 7,	/** Depth bias/polygon offset units, try to avoid using this -> see ZBias (float to PLCore::uint32 example PLCore::Tools::FloatToUInt32(-2.0f), default: 0) */
		/** Blend */
		BlendEnable         = 8,	/** Enable/disable blending (false/true, default: false) */
		SrcBlendFunc        = 9,	/** Source blend function (see BlendFunc, default: BlendFunc::SrcAlpha) */
		DstBlendFunc        = 10,	/** Destination blend function (see BlendFunc, default: BlendFunc::InvSrcAlpha) */
		/** Stencil */
		StencilEnable       = 11,	/** Enable/disable stencil test (false/true, default: false) */
		StencilFunc         = 12,	/** Stencil test passes if ((ref & mask) stencilfn (stencil & mask)) is true (see Compare, default: Compare::Always) */
		StencilRef          = 13,	/** Reference value used in stencil test (PLCore::uint32, default: 0) */
		StencilMask         = 14,	/** Mask value used in stencil test (PLCore::uint32, default: 0xFFFFFFFF) */
		StencilFail         = 15,	/** Operation to perform if stencil test fails (StencilOp, default: StencilOp::Keep) */
		StencilZFail        = 16,	/** Operation to perform if stencil test passes and Z test fails (StencilOp, default: StencilOp::Keep) */
		StencilPass         = 17,	/** Operation to perform if both stencil and Z tests pass (StencilOp, default: StencilOp::Keep) */
		TwoSidedStencilMode = 18,	/** Enable/disable 2 sided stenciling (false/true, default: false, requires Capabilities::bTwoSidedStencils)
										 If the triangle winding order is clockwise, the Stencil* operations will be used. If the winding
										 order is counterclockwise, the CCWStencil* operations will be used. */
		CCWStencilFunc      = 19,	/** Stencil test passes if ((ref & mask) stencilfn (stencil & mask)) is true (see Compare, default: Compare::Always, requires Capabilities::bTwoSidedStencils) */
		CCWStencilFail      = 20,	/** Operation to perform if ccw stencil test fails (StencilOp, default: StencilOp::Keep, requires Capabilities::bTwoSidedStencils) */
		CCWStencilZFail     = 21,	/** Operation to perform if ccw stencil test passes and Z test fails (StencilOp, default: StencilOp::Keep, requires Capabilities::bTwoSidedStencils) */
		CCWStencilPass      = 22,	/** Operation to perform if both ccw stencil and Z tests pass (StencilOp, default: StencilOp::Keep, requires Capabilities::bTwoSidedStencils) */
		/** Point and line */
		PointSize           = 23,	/** Point size when it is not specified for each vertex. (float, default: 1.0)
										 This value is in screen space units if RenderState::PointScaleEnable is false; otherwise this value is in world space units. */
		PointScaleEnable    = 24,	/** Controls computation of size for point primitives. (false/true, default: false)
										 When true, the point size is interpreted as a camera space value and is scaled by the distance function and the frustum
										 to viewport y-axis scaling to compute the final screen-space point size. When false, the point size is interpreted as screen
										 space and used directly. */
		PointSizeMin        = 25,	/** Minimum size of point primitives (float, default: 1.0, requires Capabilities::bPointParameters) */
		PointSizeMax        = 26,	/** Maximum size of point primitives, must be greater than or equal to PointSizeMin (float, default: 64.0, requires Capabilities::bPointParameters) */
		PointScaleA         = 27,	/** Controls for distance-based size attenuation for point primitives (float, default: 1.0, requires Capabilities::bPointParameters) */
		PointScaleB         = 28,	/** Controls for distance-based size attenuation for point primitives (float, default: 0.0, requires Capabilities::bPointParameters) */
		PointScaleC         = 29,	/** Controls for distance-based size attenuation for point primitives (float, default: 0.0, requires Capabilities::bPointParameters) */
		LineWidth			= 30,	/** Line width (float, default: 1.0) */
		/** Tessellation. */
		TessellationFactor  = 31,	/** Tessellation factor (1-Capabilities::nMaxTessellationFactor inclusive, default: 1, requires Capabilities::nMaxTessellationFactor > 1) */
		TessellationMode    = 32,	/** Tessellation mode (default: TessellationMode::Discrete, requires Capabilities::nMaxTessellationFactor > 1) */
		/** Misc */
		PointSpriteEnable   = 33,	/** When true, use point texture mapping (false/true, default: false, requires Capabilities::bPointSprite) */
		DitherEnable        = 34,	/** Enable/disable dithering (false/true, default: false) */
		ScissorTestEnable   = 35,	/** Enable/disable the scissor test (false/true, default: false) */
		MultisampleEnable   = 36,	/** When true, perform multisample (false/true, default: true, requires Capabilities::nMultisampleAntialiasingSamples > 1, usually set automatically by the surfaces) */
		DepthClamp          = 37,	/** Depth clamp (default: false) */
		InvCullMode         = 38,	/** Inverse cull mode active? RenderState::CullMode isn't touched only the intern API setting
										 is inverted! (false/true, default: false) */
		FixedFillMode       = 39,	/** General fill mode which is normally set once. If this isn't Fill::Unknown this fill mode
										 will be used instead of RenderState::FillMode (see Fill, default: Fill::Unknown) */
		/** End */
		Number              = 40,	/** Number of render states */
	};
};

class Sampler 
{
public:
	enum Enum 
	{
		Address,
		Filter,
		Number 
	};
};

class SamplerAddressMode
{
public:
	enum
	{
		ADDRESS_WRAP,
		ADDRESS_CLAMP,
		Number
	};
};

class SamplerFilterMode
{
public:
	enum
	{
		FILTER_NEAREST,
		FILTER_BILINEAR,
		FILTER_TRILINEAR,
		Number
	};
};

class Clear 
{
public:
	enum 
	{
		Color   = 1<<0,	/** Clear color buffer */
		ZBuffer = 1<<1,	/** Clear z buffer */
		Stencil = 1<<2	/** Clear stencil buffer */
	};
};

class Fill
{
public:
	enum
	{
		Point   = 0,	/** Point fill mode */
		Line    = 1,	/** Line fill mode */
		Solid   = 2,	/** Solid fill mode */
		Number  = 3,	/** Number of fill modes */
		Unknown = 4		/** Unknown fill mode */
	};
};

class Cull 
{
public:
	enum 
	{
		None    = 0,	/** No culling */
		CW      = 1,	/** Selects clockwise polygons as front-facing */
		CCW     = 2,	/** Selects counterclockwise polygons as front-facing */
		// End
		Number  = 3,	/** Number of cull modes */
		Unknown = 4		/** Unknown cull mode */
	};

};

enum
{
	MAX_RENDER_TARGET_COLOR_BUFFER = 8
};

class Compare
{
public:
	enum
	{
		Never        = 0,	/** Never passes */
		Less         = 1,	/** Passes if the incoming value is less than the stored value */
		Equal        = 2,	/** Passes if the incoming value is equal to the stored value */
		LessEqual    = 3,	/** Passes if the incoming value is less than or equal to the stored value */
		Greater      = 4,	/** Passes if the incoming value is greater than the stored value */
		NotEqual     = 5,	/** Passes if the incoming value is not equal to the stored value */
		GreaterEqual = 6,	/** Passes if the incoming value is greater than or equal to the stored value */
		Always       = 7,	/** Always passes */
		Number       = 8,	/** Number of comparison functions */
	};
};

class BlendFunc
{
public:
	enum
	{
		// Source & Destination
		Zero        = 0,	/** Zero */
		One         = 1,	/** One */
		// Source
		SrcColor    = 2,	/** Source color */
		InvSrcColor = 3,	/** Inverted src color */
		SrcAlpha    = 4,	/** Source alpha */
		InvSrcAlpha = 5,	/** Inverted source alpha */
		SrcAlphaSat = 6,	/** Source alpha saturate */
		// Destination
		DstColor    = 7,	/** Destination color */
		InvDstColor = 8,	/** Inverted destination color */
		DstAlpha    = 9,	/** Destination alpha */
		InvDstAlpha = 10,	/** Inverted destination alpha */
		// End
		Number      = 11,	/** Number of blend functions */
	};
};

class PixelFormat
{
public:
	enum 
	{
		U1,
		U3, 
		U4,
		U16_1,
		U16_2,
		U16_4,
		D16,
		D24,
		D32,
		DXT1,
		DXT3,
		DXT5,
		F16_1,
		F16_2,
		F16_4,
		F32_1,
		F32_2,
		F32_4,
		Number
	};
};
}